Skip to content

Conversation

@thgrund
Copy link

@thgrund thgrund commented Aug 8, 2025

I optimized the even highlighting performance with replacing the message queue mechanism. The calculation will be done completely by a web worker, that stores all incoming events and calculates the sets for added, active and removed events. These sets will be used for adding and removing markers.

This increases the user experience especially during editing big files.

thgrund and others added 18 commits August 8, 2025 19:57
Add styles

Use MrReason setup directory as stack enrtry point

Change stack package path

Continue rebasing

Continue rebasing

Continue rebasing

Continue rebasing

Continue rebasing

Continue rebasing

Continue rebasing

Continue rebasing

Continue rebasing

Continue rebasing

Continue rebasing

Continue rebasing

Continue rebasing

Continue rebasing

Fix remaining rebase issues

Fix remote control

Add safety check

Handle osc style changes

Add a event highlighting web worker

Replace old event queue with worker queue

Add set tests

Remove rebase duplication
@thgrund
Copy link
Author

thgrund commented Aug 8, 2025

@ndr-brt I really appreciate your review and feedback!
I splitted my TODOs so that the MRs will be easier for reviewing. My suggestion is to wait for a release, until the optimizations and new featuers are implemented. WDYT?

And sorry for the mess with the git history. I cleaned everything with interactive rebase...and then messed it up in the last step xD - I would really appreaciate, if you could do a squash merge when merging.

@ndr-brt ndr-brt self-requested a review August 9, 2025 13:15
Copy link
Collaborator

@ndr-brt ndr-brt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@thgrund ok for me to wait, I'll only release when you'll fill comfortable with the progress.

np with the git history: I always squash in a single commit :)

let messageBuffer = new Map();
let receivedThisFrame = new Map();

self.onmessage = function(e) {
Copy link
Collaborator

@ndr-brt ndr-brt Aug 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not really an expert in js workers, but I see that after the instantiation (event-highlighter.js:52), this onmessage field is overridden. Is then this assignment useless?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, this is the function that will be triggered, when the web worker receives messages from the main thread. The other one in in event-highlighter.js:52 is the function that will be triggered, when the main thread receives a message from the web worker.

This is the hole main idea. Doing the calculation and message buffer handling within a separate thread and independant from the animation frame.


/** Store events until the next animation frame */
function queueEvent(event) {
const messageBufferMap = ensureNestedMap(messageBuffer, event.eventId);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this const is never used

messageBuffer = EventMapHelper.transformedEvents(added.union(active));
receivedThisFrame.clear();

}, 1000/30);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

magic number, could it be extracted in a const with a meaningful name?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a const for this. I wasn't sure how I wanna handle this. Now the animation is locked by a maximum of 30FPS. Maybe I will make it configurable at a later point again, but the web worker has no access of the atom config properties, because they are only available within the main thread.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

this.startWorker();
}

startWorker() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this method can be private

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

this.filteredMessages = new Map(); // eventId → event
this.receivedThisFrame = new Map(); // eventId → event
this.addedThisFrame = new Set(); // Set<event>
this.oscStyleIds = new Set(); // received ids
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this field is never used

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed it.

Yeah...For the sake of transparency, I implement features within a separate feature branch to try out some certain implementations. And I messed up the previous rebase, this is why this stuff unfortunately appears within this MR

@@ -0,0 +1,59 @@
'use babel'

class EventMapHelper {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I admit, I'm not the biggest fan of "helpers" and "utils" classes, so I'd suggest to avoid them as much as possible.

In this case, both the functions are only used by the worker, so could them be moved there?

Copy link
Author

@thgrund thgrund Aug 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Me neither. But I am not able to define functions within the web worker and test them properly, because the jasmine tests only works within the main thread. This means I can not simply export them, because a worker is not a module. This would be the tradeoff: extract them somehow (class method or static function) or removing the tests. And to test the worker within the main thread is already an integration test.

return { removed, added, active};
}

static transformedEvents(events) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the name is quite vague, could it be called setToMap or groupByEventIdAndColStart (maybe the first is better :) )

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -0,0 +1,15 @@
if (!Set.prototype.union) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

of these 3 methods, only union is actually used, and just once.
tbh I would avoid the hassle to define and have to require the polyfills set here and there and just inline the union method where it's used (worker)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For me this felt odd to not have difference and intersections, but I agree. I removed the other ones.
Unfortunately when I move this union definition into the worker file, then it is not possible to add a unit test for this (see: #223 (comment))

lib/osc-eval.js Outdated
}

tidalRepl.eval(message['type'], false);
if (message['search']) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this changelog related to the scope of the PR?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, I removed it.

@thgrund thgrund changed the title Optimize event highlighting performance [Event Highlighting]: Optimize event highlighting performance Aug 11, 2025
@thgrund thgrund changed the title [Event Highlighting]: Optimize event highlighting performance [Event Highlighting]: Optimize performance Aug 11, 2025
@thgrund thgrund changed the title [Event Highlighting]: Optimize performance Draft: [Event Highlighting]: Optimize performance Aug 12, 2025
@thgrund thgrund marked this pull request as draft August 12, 2025 14:27
@thgrund thgrund changed the title Draft: [Event Highlighting]: Optimize performance Draft: [Event Highlighting]: Add a web worker for outsourcing the marker calculation Aug 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants